package com.tjbklx1.redis.chap04;

import java.util.List;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.Tuple;

/**
 * 测试 TRANSACTION
 * 
 * @author tjbklx1
 * @date 2018-12-5
 */
public class App41 {
	public static void main(String[] args) throws InterruptedException {
		Jedis conn = new Jedis("localhost");
		conn.select(0);
		new App41().testListItem(conn, false);
	}


	public void testListItem(Jedis conn, boolean nested) {
		if (!nested) {
			System.out.println("\n----- testListItem -----");
		}

		System.out.println("We need to set up just enough state so that a user can list an item");
		String seller = "userX"; // 卖主
		String item = "itemX"; // 物品
		conn.sadd("inventory:" + seller, item); //卖主的库存  set
		
		//查看卖主的库存
		Set<String> i = conn.smembers("inventory:" + seller);
		System.out.println("The user's inventory has:");
		for (String member : i) {
			System.out.println("  " + member);
		}
		assert i.size() > 0;
		System.out.println();

		System.out.println("Listing the item...");
		boolean l = listItem(conn, item, seller, 10);
		System.out.println("Listing the item succeeded? " + l);
		assert l;
		
		//查看市场的物品 ZSET,score=0
		Set<Tuple> r = conn.zrangeWithScores("market:", 0, -1);  
		System.out.println("The market contains:");
		for (Tuple tuple : r) {
			System.out.println("  " + tuple.getElement() + ", " + tuple.getScore());
		}
		assert r.size() > 0;
	}

	/**
	 * 将卖主的物品移动到市场中 (以transaction方式)
	 * @param conn
	 * @param itemId
	 * @param sellerId
	 * @param price
	 * @return
	 */
	public boolean listItem(Jedis conn, String itemId, String sellerId, double price) {

		String inventory = "inventory:" + sellerId;  // 卖主的库存KEY
		String item = itemId + '.' + sellerId; //卖主的物品
		
		long end = System.currentTimeMillis() + 5000;

		while (System.currentTimeMillis() < end) { //5秒内
			// watch unwatch 
			conn.watch(inventory); //watch 卖主的库存
			if (!conn.sismember(inventory, itemId)) { // 如果物品不存在就unwatch,return
				conn.unwatch();
				return false;
			}

			// 核心代码 ,transaction multi,exec
			Transaction trans = conn.multi(); //开启一个事务
			trans.zadd("market:", price, item); //将物品放到market
			trans.srem(inventory, itemId); //将物品从卖主的库存中删除
			List<Object> results = trans.exec(); //执行事务
			
			// null response indicates that the transaction was aborted due to the watched key changing.
			if (results == null) {
				continue;
			}
			return true;
		}
		return false;
	}
}
